package menu

import (
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"menu-generation-go/database"
	"menu-generation-go/handlers/common"
	"menu-generation-go/models"
	"sync"
)

type MenuFoodIngredientHandler struct {
	DB *database.Database
}

func NewMenuFoodIngredientHandler(db *database.Database) *MenuFoodIngredientHandler {
	return &MenuFoodIngredientHandler{DB: db}
}

// GetIngredientsByType 根据类型获取食材列表(分页)
func (h *MenuFoodIngredientHandler) GetIngredientsByType(c *gin.Context) {
	// 解析类型参数
	var req struct {
		Type   int    `form:"type" binding:"required,min=1,max=5"`
		Search string `form:"search"`
	}
	if err := c.ShouldBindQuery(&req); err != nil {
		common.SendErrJSON(err.Error(), c)
		return
	}

	// 解析分页参数
	pagination := &models.Pagination{}
	if err := c.ShouldBindQuery(pagination); err != nil {
		common.SendErrJSON(err.Error(), c)
		return
	}

	// 查询数据
	result, err := models.GetIngredientsByType(h.DB.GetDB(), req.Type, req.Search, pagination)
	if err != nil {
		common.SendErrJSON(err.Error(), c)
		return
	}

	common.Ok(c, result)
}

// GetCategoryCounts 获取所有分类的食材数量统计
func (h *MenuFoodIngredientHandler) GetCategoryCounts(c *gin.Context) {
	type CategoryCount struct {
		Type  int `json:"type"`
		Count int `json:"count"`
	}

	// 定义所有分类类型
	categories := []int{1, 2, 3, 4, 5} // 对应前端5个分类
	// 使用waitgroup实现并发查询
	var wg sync.WaitGroup
	resultChan := make(chan CategoryCount, len(categories))

	for _, categoryType := range categories {
		wg.Add(1)
		go func(t int) {
			defer wg.Done()
			var count int64
			h.DB.GetDB().Model(&models.MenuFoodIngredient{}).Where("type = ? and status = 1", t).Count(&count)
			resultChan <- CategoryCount{Type: t, Count: int(count)}
		}(categoryType)
	}

	// 等待所有goroutine完成
	go func() {
		wg.Wait()
		close(resultChan)
	}()

	// 收集结果
	results := make(map[int]int)
	for res := range resultChan {
		results[res.Type] = res.Count
	}

	// 按前端需要的顺序返回
	response := []gin.H{}
	for _, t := range categories {
		response = append(response, gin.H{
			"type":  t,
			"count": results[t],
			"name":  models.IngredientTypes[t], // 使用之前定义的分类名称映射
		})
	}

	common.Ok(c, response)
}

func (h *MenuFoodIngredientHandler) AddCategoryMenu(c *gin.Context) {
	var input struct {
		Name        string `json:"name" binding:"required,min=1,max=255"`
		Type        int    `json:"type" binding:"required,min=1,max=5"`
		Description string `json:"description" binding:"max=255"`
		Unit        string `json:"unit" binding:"max=50"`
	}

	// 参数绑定校验
	if err := c.ShouldBindJSON(&input); err != nil {
		common.SendErrJSON("参数错误", c)
		return
	}

	// 检查同类型下菜品名称是否已存在
	var existing models.MenuFoodIngredient
	if err := h.DB.GetDB().Where("name = ? AND type = ?", input.Name, input.Type).First(&existing).Error; err == nil {
		common.SendErrJSON("该分类下已存在同名菜品!", c)
		return
	} else if err != gorm.ErrRecordNotFound {
		common.SendErrJSON("操作异常!", c)
		return
	}

	// 创建新菜品
	newDish := models.MenuFoodIngredient{
		Name:        input.Name,
		Type:        input.Type,
		Description: input.Description,
		Unit:        input.Unit,
		Status:      1, // 默认正常状态
	}

	if err := h.DB.GetDB().Create(&newDish).Error; err != nil {
		common.SendErrJSON("创建失败!", c)
		return
	}
	common.Ok(c, "创建成功")
}

func (h *MenuFoodIngredientHandler) UpdateCategoryMenu(c *gin.Context) {

	var input models.MenuFoodIngredient
	if err := c.ShouldBindJSON(&input); err != nil {
		common.SendErrJSON("参数错误: "+err.Error(), c)
		return
	}

	// 检查菜品是否存在
	var existing models.MenuFoodIngredient
	if err := h.DB.GetDB().Where("id = ?", input.ID).First(&existing).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			common.SendErrJSON("菜品不存在", c)
		} else {
			common.SendErrJSON("操作异常", c)
		}
		return
	}

	// 如果传入了name，检查同类型下是否有其他同名菜品
	if input.Name != "" && input.Name != existing.Name {
		var duplicate models.MenuFoodIngredient
		queryType := existing.Type
		if input.Type != 0 {
			queryType = input.Type
		}

		if err := h.DB.GetDB().Where("name = ? AND type = ? AND id != ?", input.Name, queryType, input.ID).First(&duplicate).Error; err == nil {
			common.SendErrJSON("该分类下已存在同名菜品!", c)
			return
		} else if err != gorm.ErrRecordNotFound {
			common.SendErrJSON("操作异常!", c)
			return
		}
	}

	// 构建更新数据
	updates := make(map[string]interface{})
	if input.Name != "" {
		updates["name"] = input.Name
	}
	if input.Type != 0 {
		updates["type"] = input.Type
	}
	if input.Description != "" {
		updates["description"] = input.Description
	}
	if input.Unit != "" {
		updates["unit"] = input.Unit
	}

	// 如果没有可更新字段
	if len(updates) == 0 {
		common.SendErrJSON("没有可更新的字段", c)
		return
	}

	// 执行更新
	if err := h.DB.GetDB().Model(&models.MenuFoodIngredient{}).Where("id = ?", input.ID).Updates(updates).Error; err != nil {
		common.SendErrJSON("更新失败", c)
		return
	}

	common.Ok(c, "更新成功")
}

// 请求参数结构体
type DeleteRequest struct {
	ID int `json:"id" binding:"required,min=1"` // 必须传递ID
}

func (h *MenuFoodIngredientHandler) DeleteCategoryMenu(c *gin.Context) {
	// 绑定JSON参数
	var input DeleteRequest
	if err := c.ShouldBindJSON(&input); err != nil {
		common.SendErrJSON("参数错误: "+err.Error(), c)
		return
	}

	// 检查菜品是否存在
	var existing models.MenuFoodIngredient
	if err := h.DB.GetDB().Where("id = ?", input.ID).First(&existing).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			common.SendErrJSON("菜品不存在", c)
		} else {
			common.SendErrJSON("操作异常", c)
		}
		return
	}

	// 检查菜品是否已被删除
	if existing.Status == 0 {
		common.SendErrJSON("菜品已被删除", c)
		return
	}

	// 执行软删除（更新状态为0）
	if err := h.DB.GetDB().Model(&models.MenuFoodIngredient{}).
		Where("id = ?", input.ID).
		Update("status", 0).Error; err != nil {
		common.SendErrJSON("删除失败", c)
		return
	}

	common.Ok(c, "删除成功")
}
